/**
 * 
 */
package ptvv;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author dkz
 * 
 */
public abstract class DefaultAutomata extends Thread {
	protected InternalStates internalState = InternalStates.Starting;
	protected Trace logger = Trace.getLogger();
	protected BlockingQueue<String> eventQueue = new LinkedBlockingQueue<String>(); // start

	protected BlockingQueue<String> inputPort = new LinkedBlockingQueue<String>(); // input
	protected OutputPort outputPort; // output
	protected boolean repeatBool = false;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	public void setThreadAndClass(ThreadAndClass temp) {
		outputPort = new OutputPort(temp.autoclass, temp.autothread);
	}

	public InternalStates getInternalState() {
		return internalState;
	}

	public void runStates() {
		try {
			switch (internalState) {
			case Starting:
				starting();
				this.internalState = InternalStates.Ready;
				break;
			case Ready:
				ready();
				this.internalState = InternalStates.Running;
				break;
			case Running:
				running();
				this.internalState = InternalStates.End;
				break;
			case Suspended:
				suspended();
				this.internalState = InternalStates.Running;
				break;
			case End:
				end();
				this.internalState = InternalStates.Dead;
				break;
			case Dead:
				dead();
				this.internalState = InternalStates.ReallyDead;

			}
			if (repeatBool) {
				this.internalState = InternalStates.Starting;
				repeatBool = false;
			}

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// logger.log(this.getName() + ": " + internalState.toString());

	}

	public abstract void starting() throws InterruptedException;

	public abstract void ready() throws InterruptedException;

	public abstract void running() throws InterruptedException;

	public abstract void suspended() throws InterruptedException;

	public abstract void end() throws InterruptedException;

	public abstract void dead() throws InterruptedException;

	public void addEvent(String str) {
		try {
			eventQueue.put(str);
		} catch (InterruptedException iex) {
			Thread.currentThread().interrupt();
			throw new RuntimeException("Unexpected interruption");
		}
	}

	public void addInput(String str) {

		try {
			inputPort.put(str);
		} catch (InterruptedException iex) {
			Thread.currentThread().interrupt();
			throw new RuntimeException("Unexpected interruption");
		}
	}

	public void run() {
		while (internalState != InternalStates.ReallyDead)
			runStates();

		// logger.log("SHUTDOWN");
	}
}
